import _thread as thread
import time
import numpy
import brain
import random

class Space:
    #基础“微粒“大小
    BASESIZE = 10
    #世界大小，也就是窗口的大小
    SPACE_WIDTH = 100
    SPACE_HEIGHT = 60
    #基本时间单位1秒
    BASETIME = 1
    
    #创建一个世界：一个二维矩阵
    WORLD_MATRIX = numpy.zeros((SPACE_HEIGHT, SPACE_WIDTH),dtype=int)
    
    #方向
    #北方
    DIRECTION_NORTH = 0
    #东方
    DIRECTION_EAST = 1
    #南方
    DIRECTION_SOUTH = 2
    #西方
    DIRECTION_WEST = 3
    
    #视野范围
    VIEW_LEN = 8
    
    
class Point:
    '''
    点
    大小：n x n
    '''

    '''
    size: 大小
    x: 位置 x
    y：位置 y
    '''
    def __init__(self, size, x, y):
        self.size = size
        self.x = x
        self.y = y

#柱子（建造迷宫所需材料）
class Line:
    '''
    线
    start: 在空间中的开始位置
    end: 在空间中的结束位置
    width: 线的粗细
    '''
    MT = 1#表示柱子的材料
    
    def __init__(self, color, start, end, width):
        self._attArray=[]
        self._realArray=[]
        self._attArray.append(color)
        self._attArray.append(start)
        self._attArray.append(end)
        self._attArray.append(width)
        
        self._realArray.append(color)
        self._realArray.append([start[0] * Space.BASESIZE, start[1] * Space.BASESIZE])
        self._realArray.append([end[0] * Space.BASESIZE, end[1] * Space.BASESIZE])
        self._realArray.append(width * Space.BASESIZE)
        
        #在二维世界中画出点
        if start[0] == end[0]:#竖线
            if start[1] < end[1]:
                for i in range(start[1],end[1]+1):
                    Space.WORLD_MATRIX[i][start[0]] = Line.MT
            else:
                for i in range(end[1],start[1]+1):
                    Space.WORLD_MATRIX[i][start[0]] = Line.MT
        else:
            if start[0] < end[0]:#横线:行不动，列 是范围
                Space.WORLD_MATRIX[start[1]][start[0]:end[0]+1] = Line.MT
            else:
                Space.WORLD_MATRIX[start[1]][end[0]:start[0]+1] = Line.MT
        
    def getAttArray(self):
        return self._attArray
    
    def getRealArray(self):
        return self._realArray
    
#迷宫
class Maze:
    def __init__(self):
        self.LineObjList=[]
        
    def addObjLine(self, lineObj):
        self.LineObjList.append(lineObj)
    
    def addLine(self, color, lineArray, width):
        for lineValue in lineArray:
            self.addObjLine(Line(color, lineValue[0], lineValue[1], width))
    
    def getRealLineArray(self):
        #元素为数组的集合
        RealLineArray = []
        for line in self.LineObjList:
            RealLineArray.append(line.getRealArray())
        return RealLineArray
    
    #判断点是否在迷宫点墙内
    def isIn(self, point):
        itemLineArray = []
        for line in self.LineObjList:
            itemLineArray = line.getAttArray()
            if itemLineArray[1][0] == itemLineArray[2][0]:#比较起始点x坐标
                if ((point[0] == itemLineArray[1][0]) and 
                    ((point[1] >= itemLineArray[1][1] and point[1] <= itemLineArray[2][1]) or 
                     (point[1] >= itemLineArray[2][1] and point[1] <= itemLineArray[1][1]))):#看点是否在线上
                    return True
                else:
                    return False
            else:
                if ((point[1] == itemLineArray[1][1]) and 
                    ((point[0] >= itemLineArray[1][0] and point[0] <= itemLineArray[2][0]) or 
                     (point[0] >= itemLineArray[2][0] and point[0] <= itemLineArray[1][0]))):#看点是否在线上
                    return True
                else:
                    return False

#车子
class Car:
    MT = 2
    def __init__(self, location, direction):
        self.location = []
        self.location = location
        self.direction = direction
        self.speed = 0
        self.view = [0,100,60,0]#车子的视野，四个元素的数组，分别代表北/东/南/西四个方向最近点物体距离
        self.feel =[]#车子的感觉，四个元素的数组，分别代表北/东/南/西四个方向的压力
        self.riskLen = [0,0,0,0]#危险距离，最长为6. 四个元素分别为：前右后左
        Space.WORLD_MATRIX[self.location[1]][self.location[0]] = Car.MT
#         thread.start_new_thread(self.simpleBrain,())
    
    def getRealLocation(self):
        return [self.location[0] * Space.BASESIZE, self.location[1] * Space.BASESIZE]
    
#     def simpleBrain(self):
#         while(True):
#             for i in range(4):
#                 itemIndex = (self.direction + i)%4
#                 itemValue = self.view[itemIndex]
#                 if itemValue > Space.VIEW_LEN:
#                     itemValue = Space.VIEW_LEN
#                 if (i == 1 or i == 3) and itemValue != Space.VIEW_LEN:
#                     itemValue *= 0.7
#                 elif i == 2 and itemValue != Space.VIEW_LEN:
#                     itemValue *= 0.5
#                 self.riskLen[i] = itemValue
#             
#             safeDir = []
#             maxI = -1
#             for i,e in enumerate(self.riskLen):
#                 if e > Space.VIEW_LEN-0.1:
#                     safeDir.append(i)
#                 else:
#                     if maxI != -1:
#                         maxI = i
#                     else:
#                         if self.riskLen[i] > self.riskLen[maxI]:
#                             maxI = i
#             
#             #从安全方向中随机取一个
#             if safeDir:#不空
#                 maxI = random.choice(safeDir)
#             
#             self.direction = (self.direction + maxI)%4
#             
#             #如果车子停了，就再次启动
#             if self.speed == 0:
#                 self.speed = 1
#             #根据危险距离改变方向
#             time.sleep(Space.BASETIME)
    
                        
#自然中控
class World:
    def __init__(self):
        #创建一个迷宫
        BLUE = (0, 0, 255)
        lineWidth = 1
        lineArray = [[(70,45), (70,15)], [(70,15), (30, 15)], [(30, 15), (30, 45)], [(30, 45), 
                    (65, 45)], [(65, 45), (65, 20)], [(65, 20), (35, 20)], [(35, 20), (35, 40)], [(35, 40), 
                    (60, 40)], [(60, 40), (60, 25)], [(60, 25), (40, 25)], [(40, 25), (40, 35)], [(40, 35),
                    (55, 35)], [(55, 35), (55, 30)], [(55, 30), (45, 30)]]
        self.maze = Maze()
        self.maze.addLine(BLUE, lineArray, lineWidth)
        
        #创建一个车子
        self.car = Car((1,1), Space.DIRECTION_EAST)
        
        #开启线程：监听车子状况
        thread.start_new_thread(self._carStatus, (self.car, self.maze,))
        #开启线程：让车子看到周围障碍物
        thread.start_new_thread(self._carSee, (self.car,))
        #开启上帝视角大脑，用来控制车子
        brain.TBrain(self.car)
        
    
    #判断车子是否撞墙  
    def isCarHit(self, car, maze):
        if car.speed == 0:
            return False
        if Space.DIRECTION_NORTH ==  car.direction:
            return maze.isIn([car.location[0],car.location[1]-car.speed])
        elif Space.DIRECTION_EAST == car.direction:
            return maze.isIn([car.location[0]+car.speed,car.location[1]])
        elif Space.DIRECTION_SOUTH == car.direction:
            return maze.isIn([car.location[0],car.location[1]+car.speed])
        elif Space.DIRECTION_WEST == car.direction:
            return maze.isIn([car.location[0]-car.speed,car.location[1]])
        else:
            return True
    
    #监听车子
    def _carStatus(self, car, maze):
        while car.speed > 0:
            if self.isCarHit(car, maze):
                car.speed = 0 #撞墙停止
                #撞击程度用速度表示
                car.feel[Space.DIRECTION_NORTH] = car.speed
            else:
                #没撞墙，继续往前走 
                #抹除二维世界中点车点
                Space.WORLD_MATRIX[car.location[1]][car.location[0]] = 0
                if Space.DIRECTION_NORTH ==  car.direction:
                    car.location = [car.location[0], car.location[1] - car.speed]
                elif Space.DIRECTION_EAST == car.direction:
                    car.location = [car.location[0] + car.speed, car.location[1]]
                elif Space.DIRECTION_SOUTH == car.direction:
                    car.location = [car.location[0], car.location[1] + car.speed]
                elif Space.DIRECTION_WEST == car.direction:
                    car.location = [car.location[0] - car.speed, car.location[1]]
                else:
                    print("方向错误")
                #绘制二维世界新车位置
                Space.WORLD_MATRIX[car.location[1]][car.location[0]] = Car.MT
#                 print(car.location, car.view)
                
            time.sleep(Space.BASETIME)
    
    #让车子可以看到周围障碍物--这一段有问题！！
    def _carSee(self, car):
        while True:
            print("location=", car.location, ",direction=", car.direction, ",view=", car.view, ",riskLen=", car.riskLen)
            #-------------------------横轴方向两个距离（矩阵点第二个参数变动）------------------------
            overFlag = True
            i = 0#遍历序号
            car.view[3] = 0
            for i,p in enumerate(Space.WORLD_MATRIX[car.location[1]][car.location[0]::-1]):
                if i != 0 and p != 0:
                    car.view[3] = i
                    overFlag = False
                    break
            if overFlag:
                car.view[3] = i
               
            overFlag = True
            i = 0#遍历序号
            car.view[1] = 0
            for i,p in enumerate(Space.WORLD_MATRIX[car.location[1]][car.location[0]:]):
                if i != 0 and p != 0:
                    car.view[1] = i
                    overFlag = False
                    break
            if overFlag:
                car.view[1] = i
            
            #-------------------------纵轴方向两个距离（矩阵点第一个参数变动，无法使用矩阵切片）------------------------ 
            overFlag = True
            i = 0#遍历序号   
            car.view[2] = 0
            for i,y in enumerate(range(car.location[1], Space.SPACE_HEIGHT)):
#                 print(i,y)
                p = Space.WORLD_MATRIX[y][car.location[0]]
                if i != 0 and p != 0:
                    car.view[2] = i
                    overFlag = False
                    break
            if overFlag:
                car.view[2] = i
            
            overFlag = True
            i = 0#遍历序号     
            car.view[0] = 0
            for i,y in enumerate(range(car.location[1], -1, -1)):
                p = Space.WORLD_MATRIX[y][car.location[0]]#混淆点:矩阵（数组）点【】【】并不是指代x，y，而是恰恰相反，指的是y，x
                if i != 0 and p != 0:
                    car.view[0] = i
                    overFlag = False
                    break
            if overFlag:
                car.view[0] = i
                
            
            time.sleep(Space.BASETIME)
    
    #获取迷宫
    def getMaze(self):
        return self.maze
    #获取车子
    def getCar(self):
        return self.car

def drawMatrix(mat):
    for i in range(60):
        for j in range(100):
            if (j != 99):
                print(mat[i][j],"",end="")
            else:
                print(mat[i][j],"")
                


    

def main():
#     BLUE = (0, 0, 255)
#     lineWidth = 1
#     lineArray = [[(70,45), (70,15)], [(70,15), (30, 15)], [(30, 15), (30, 45)], [(30, 45), 
#                 (65, 45)], [(65, 45), (65, 20)], [(65, 20), (35, 20)], [(35, 20), (35, 40)], [(35, 40), 
#                 (60, 40)], [(60, 40), (60, 25)], [(60, 25), (40, 25)], [(40, 25), (40, 35)], [(40, 35),
#                 (55, 35)], [(55, 35), (55, 30)], [(55, 30), (45, 30)]]
#     maze = Maze()
#     maze.addLine(BLUE, lineArray, lineWidth)
    #创建一个世界
    world = World()
    time.sleep(600)
    #一秒钟打印一下车子点位置

#     print(maze.getjRealLineArray())
#     drawMatrix(Space.WORLD_MATRIX)

    
    
if __name__ == '__main__':
    main()
    